﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Drawing;

namespace SmartProject.AppSpace
{
    public partial class Download : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                string id = Request.QueryString["ID"];
                string action = Request.QueryString["Action"];
                if (!String.IsNullOrEmpty(id))
                {
                    if (action == "BurndownChart")
                    {
                        DrawBurnDownChart(Convert.ToInt32(id));
                        return;
                    }

                    int attachmentId = Convert.ToInt32(id);
                    BusinessObjects.Attachment attachment
                        = new SmartProject.BusinessObjects.Attachment();
                    attachment.SetAttribute("AttachmentId", attachmentId);
                    attachment.Load();

                    string fileType = attachment.AttachmentFileType.GetValue(
                        (int)attachment.GetAttributeValue("FiletypeId"));

                    Response.ContentType =
                        attachment.AttachmentFileType.GetMimeType(fileType);


                    if (!String.IsNullOrEmpty(action) &&
                        action.ToLower() == "download")
                    {
                        string fileName = (string)attachment.GetAttributeValue("Filename");
                        Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}", fileName));
                        Response.BinaryWrite((byte[])attachment.GetAttributeValue("Filecontent"));
                        Response.End();
                        return;
                    }

                    if (attachment.AttachmentFileType.IsImageFile(fileType))
                    {
                        Response.BinaryWrite((byte[])attachment.GetAttributeValue("Filecontent"));
                    }
                    else
                    {
                        string fileName = (string)attachment.GetAttributeValue("Filename");
                        Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}", fileName));
                        Response.BinaryWrite((byte[])attachment.GetAttributeValue("Filecontent"));
                        Response.End();
                    }
                }
            }
        }

        private const float _fontSize = 7.5F;
        private const int _heightBufferTop = 10;
        private const int _heightBufferBottom = 55;
        private const int _widthBufferLeft = 23;
        private const int _widthBufferRight = 2;
        private const int _pixelsPerHour = 2;
        private const int _pixelsPerDay = 27;
        private const int _totalDays = 31;
        private const int _totalHours = 250;
        private Color _background = Color.FromArgb(238, 233, 233);

        private void DrawBurnDownChart(int sprintId)
        {
            BusinessObjects.Sprint sprint = new SmartProject.BusinessObjects.Sprint();
            sprint.SetAttribute("SprintId", sprintId);
            sprint.Load();

            DateTime startDate = (DateTime)sprint.GetAttributeValue("Started");
            int estimatedDays = (int)sprint.GetAttributeValue("EstimatedDays");

            Preference preference = new Preference();
            preference.GetValue("DailyWorkHours");
            int workHoursPerDay = Convert.ToInt32(preference.Value);

            BusinessObjects.Work work = new SmartProject.BusinessObjects.Work();
            work.SetAttribute("SprintId", sprintId);
            System.Data.DataTable works = work.LoadSprintWorks();
            int[] dailyMinutes = null;
            TimeSpan span = DateTime.Today - startDate;
            int totalMinutes = 0;
            if (works != null && span.Days > 0)
            {
                BusinessObjects.TimeType timeType =
                    new SmartProject.BusinessObjects.TimeType();
                DateTime lastDate = startDate;
                dailyMinutes = new int[span.Days];
                for (int i = 0; i < works.Rows.Count; i++)
                {
                    System.Data.DataRow row = works.Rows[i];
                    DateTime completed = (DateTime)row["Completed"];
                    TimeSpan daysDiff = completed.Date - startDate.Date;
                    int timeValue = (int)row["ActualTime"];
                    switch (timeType.GetValue((int)row["ActualTimeTypeId"]))
                    {
                        case "Minute(s)":
                            // Do nothing.
                            break;

                        case "Hour(s)":
                            timeValue = (timeValue * 60);
                            break;

                        case "Day(s)":
                            timeValue = (timeValue * 60 * workHoursPerDay);
                            break;
                    }

                    if (completed.Date >= startDate.Date)
                    {
                        dailyMinutes[daysDiff.Days] += timeValue;
                    }
                    totalMinutes += timeValue;
                }
            }

            //int sprintHoursTotal = estimatedDays * workHoursPerDay;
            int sprintHoursTotal = Convert.ToInt32((double)totalMinutes / 60F);
            int drawAreaHeight = _pixelsPerHour * _totalHours;
            int height = drawAreaHeight + _heightBufferTop + _heightBufferBottom;
            int drawAreaWidth = _pixelsPerDay * _totalDays;
            int width = drawAreaWidth + _widthBufferLeft + _widthBufferRight;
            using (Bitmap bitmap = new Bitmap(width, height,
                System.Drawing.Imaging.PixelFormat.Format24bppRgb))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    using (SolidBrush green = new SolidBrush(_background))
                    {
                        g.FillRectangle(green, 0, 0, width, height);
                        green.Dispose();
                    }

                    using (SolidBrush black = new SolidBrush(Color.Black))
                    {
                        using (Pen pen = new Pen(Color.Black))
                        {
                            pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
                            pen.DashOffset = 30;

                            Font font = new Font("Arial", _fontSize);
                            int start = _heightBufferTop + 1;
                            int end = width - _widthBufferRight;
                            int textYTopBuffer = Convert.ToInt32(_fontSize / 2F);
                            const int yMovement = 40;
                            int hoursDecrement = yMovement / _pixelsPerHour;
                            int totalHoursToDecrement = _totalHours;
                            for (int y = start; y < drawAreaHeight; y += yMovement)
                            {
                                g.DrawLine(pen, _widthBufferLeft, y, end, y);
                                g.DrawString(totalHoursToDecrement.ToString(), font, black, 0, y - textYTopBuffer);
                                int next = totalHoursToDecrement - hoursDecrement;
                                if (next < 0)
                                {
                                    break;
                                }
                                else
                                {
                                    totalHoursToDecrement = next;
                                }
                            }

                            if (totalHoursToDecrement != 0)
                            {
                                // Find the Y where totalHours = 0.
                                int finalY = drawAreaHeight + _heightBufferTop;
                                totalHoursToDecrement = 0;
                                g.DrawLine(pen, _widthBufferLeft, finalY, end, finalY);
                                g.DrawString("0", font, black, 0, finalY - textYTopBuffer);
                            }

                            using (Pen blue = new Pen(Color.DodgerBlue))
                            {
                                int bottom = _heightBufferTop + drawAreaHeight;
                                blue.Width = 2F;
                                Point startPoint = Point.Empty;
                                using (SolidBrush innerBlue = new SolidBrush(Color.LightSkyBlue))
                                {
                                    int dailyTotalMinutes = sprintHoursTotal * 60;
                                    int left = _widthBufferLeft;
                                    int centerIncrement = Convert.ToInt32((double)_pixelsPerDay / (double)2);
                                    for (int day = 1; day <= _totalDays; day++)
                                    {
                                        if (dailyTotalMinutes > 0)
                                        {
                                            // Make sure we draw based on the daily hours and stop when we are at Yesterday.
                                            if (dailyMinutes != null && day < dailyMinutes.Length)
                                            {
                                                int dailyHeight = Convert.ToInt32((double)dailyTotalMinutes / (double)60) * _pixelsPerHour;
                                                Rectangle area = new Rectangle(left, (bottom - dailyHeight), _pixelsPerDay, dailyHeight);
                                                g.FillRectangle(innerBlue, area);
                                                g.DrawRectangle(blue, area);
                                                dailyTotalMinutes -= dailyMinutes[day - 1];
                                            }
                                        }

                                        if (sprintHoursTotal > 0)
                                        {
                                            int sprintHeight = bottom - (sprintHoursTotal * _pixelsPerHour);
                                            Point point = new Point((day * _pixelsPerDay) + centerIncrement, sprintHeight);
                                            if (startPoint == Point.Empty)
                                            {
                                                startPoint = point;
                                                g.FillEllipse(new SolidBrush(Color.Red), point.X - 4, point.Y - 4, 8, 8);
                                            }

                                            sprintHoursTotal -= workHoursPerDay;

                                            // This represents the last day which the sprint cycle will be complete.
                                            if (sprintHoursTotal <= 0)
                                            {
                                                point = new Point(((day + 1) * _pixelsPerDay) + centerIncrement, bottom);
                                                g.FillEllipse(new SolidBrush(Color.Red), point.X - 4, point.Y - 4, 8, 8);
                                                g.DrawLine(Pens.Red, startPoint, point);
                                            }
                                        }
                                        left += _pixelsPerDay;
                                    }
                                    innerBlue.Dispose();
                                }
                                if (_heightBufferBottom > 0)
                                {
                                    //using (FontFamily arial = new FontFamily("Arial"))
                                    //{
                                    StringFormat format = new StringFormat();
                                    format.FormatFlags = StringFormatFlags.DirectionVertical;

                                    float floatY = _heightBufferTop + drawAreaHeight;
                                    // Draw days with rotatation

                                    for (int day = 0; day < _totalDays; day++)
                                    {
                                        /*
                                        System.Drawing.Drawing2D.GraphicsPath path =
                                            new System.Drawing.Drawing2D.GraphicsPath();
                                        */
                                        float floatX = (float)((day * _pixelsPerDay) + _widthBufferLeft);
                                        RectangleF layout = new RectangleF(floatX, floatY, _pixelsPerDay, _heightBufferBottom);
                                        string text = startDate.AddDays(day).ToShortDateString();
                                        /*
                                        string text = String.Format("Day {0}", day + 1);
                                        path.AddString(text, arial, (int)FontStyle.Regular, 9.5F, layout, format);
                                        g.DrawPath(Pens.Black, path);
                                        */
                                        g.DrawString(text, font, new SolidBrush(Color.Black), floatX, floatY, format);
                                    }
                                    //}
                                }
                                blue.Dispose();
                            }
                            pen.Dispose();
                        }
                        black.Dispose();
                    }
                    g.Dispose();
                }

                using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
                {
                    bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                    Response.ContentType = "image/png";
                    Response.BinaryWrite(ms.ToArray());
                    ms.Close();
                    ms.Dispose();
                }
                bitmap.Dispose();
            }
        }
    }
}
